package com.vcredit.bird.service.product;

import com.vcredit.creditcat.util.Constants;
import com.vcredit.creditcat.util.RSAUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.vcredit.bird.api.ICreditProductService;
import com.vcredit.bird.vo.product.kak.CreditKakAuditParamDto;
import com.vcredit.bird.vo.product.kak.CreditKakDecisionResult;
import com.vcredit.bird.vo.product.kak.CreditKakIdDto;
import com.vcredit.bird.vo.product.kak.CreditKakSubmitResultDto;
import com.vcredit.creditcat.exception.BirdRequestException;
import com.vcredit.creditcat.exception.ProductCanNotApplyException;
import com.vcredit.creditcat.vo.CommonResultExt;
import com.vcredit.framework.annotation.Log;
import com.vcredit.framework.util.BeanUtil;
import com.vcredit.framework.util.HttpRequest;
import com.vcredit.framework.util.JacksonUtil;

/**
 * @author 张新功
 */
@Service("creditKakService")
public class CreditKakService implements ICreditProductService {
  @Value("${creditKak.accede}")
  private String creditKakUrl;
  @Value("${creditKak.publicKey}")
  private String publicKey;
  @Value("${creditKak.privateKey}")
  private String privateKey;

  private static Logger logger = LoggerFactory.getLogger(CreditKakService.class);


  @Log
  @Override
  public Object commit(Object productParam) throws ProductCanNotApplyException, JsonParseException,
      JsonMappingException, IOException, Exception {
    Map<String, Object> resultMap = new HashMap<String, Object>();
    CreditKakIdDto kakaIdDto = new CreditKakIdDto();
    BeanUtil.copy(productParam, kakaIdDto);
    CreditKakAuditParamDto auditParamDto = new CreditKakAuditParamDto();
    BeanUtil.copy(productParam, auditParamDto);
    String noneCodePart = JacksonUtil.Obj2Json(kakaIdDto);
    String codePart = this.encodeJsonParam(JacksonUtil.Obj2Json(productParam));
    StringBuilder sbBuffer = new StringBuilder(codePart);
    sbBuffer.append("|").append(noneCodePart);
    try {
      logger.info(creditKakUrl.concat("/submitUserInfo"));
      String resultJson =
          HttpRequest.doJson(creditKakUrl.concat("/submitUserInfo"), sbBuffer.toString(), 30);
      String decodeJsonParam = this.decodeJsonParam(resultJson).replace(":\"\"", ":null");
      CommonResultExt<CreditKakSubmitResultDto> result =
          JacksonUtil.Json2Obj(decodeJsonParam,
              new TypeReference<CommonResultExt<CreditKakSubmitResultDto>>() {});
      if (!"1".equals(result.getStatus())) {
        logger.info(result.getMsg());
        resultMap.put("commitError", new CreditKakDecisionResult("error", result.getMsg()));
        return resultMap;
      }

      CreditKakSubmitResultDto resultDto = result.getData();
      String operationResult = resultDto.getOperationResult();

      if (!"true".equals(operationResult)) {
        resultMap.put("commitError", new CreditKakDecisionResult("error", result.getMsg()));
        return resultMap;
      }
    } catch (Exception e) {
      if (e instanceof ProductCanNotApplyException) {
        throw new ProductCanNotApplyException(e.getMessage());
      }
      logger.info(e.toString());
      throw new BirdRequestException("网络开小差, 请重新尝试哦。");
    }
    return auditParamDto;
  }

  @Log
  @Override
  public Object checkCredit(Object productParam) throws ProductCanNotApplyException, Exception {
    String decodeJsonParam = null;
    try {
      logger.info(creditKakUrl.concat("/getCreditAmount"));
      String resultJson =
          HttpRequest.doJson(creditKakUrl.concat("/getCreditAmount"),
              this.encodeJsonParam(JacksonUtil.Obj2Json(productParam)));
      decodeJsonParam = this.decodeJsonParam(resultJson);
    } catch (Exception e) {
      if (e instanceof ProductCanNotApplyException) {
        throw new ProductCanNotApplyException(e.getMessage());
      }
      logger.info(e.toString());
      throw new BirdRequestException("网络开小差, 请重新尝试哦。");
    }

    return decodeJsonParam;
  }

  @Log
  @Override
  public Object getCredit(Object inputDto) throws ProductCanNotApplyException, Exception {
    CommonResultExt<CreditKakDecisionResult> result = null;
    try {
      logger.info(creditKakUrl.concat("/decision"));
      String resultJson =
          HttpRequest.doJson(creditKakUrl.concat("/decision"),
              this.encodeJsonParam(JacksonUtil.Obj2Json(inputDto)), 30);
      String decodeJsonParam = this.decodeJsonParam(resultJson).replace(":\"\"", ":null");
      result =
          JacksonUtil.Json2Obj(decodeJsonParam,
              new TypeReference<CommonResultExt<CreditKakDecisionResult>>() {});
      if (!"1".equals(result.getStatus())) {//失败
        logger.info(result.getMsg());
        return new CreditKakDecisionResult("error", result.getMsg());
      }
    } catch (Exception e) {
      if (e instanceof ProductCanNotApplyException) {
        throw new ProductCanNotApplyException(e.getMessage());
      } else {
        logger.info(e.toString());
        throw new BirdRequestException("网络开小差, 请重新尝试哦。");
      }
    }
    return result.getData();
  }

  private String encodeJsonParam(String jsonParam) throws UnsupportedEncodingException,
      Exception {
    // 加密
    String requestContentBase64 =
        Base64.encodeBase64String(RSAUtil.encryptByPrivateKey(jsonParam.getBytes("utf-8"),
            this.privateKey));
    return requestContentBase64;
  }

  private String decodeJsonParam(String respJson) throws Exception {
    String result = "";
    // 解密
    byte[] res = RSAUtil.decryptBASE64(respJson);
    result = new String(RSAUtil.decryptByPublicKey(res, this.publicKey));
    return result;
  }
}
